/*
 * Copyright (c) 2010, Ivan Latysh or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */

package com.addthis.components {
import com.addthis.classes.DataLoadedEvent;
import com.addthis.classes.Service;

import flash.display.Bitmap;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;

import flash.net.URLRequest;
import flash.system.LoaderContext;

import mx.collections.ArrayCollection;
import mx.collections.XMLListCollection;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;

import spark.primitives.BitmapImage;

/* Event dispatched when service data has been loaded */
[Event(name="dataLoaded",type="com.addthis.classes.DataLoadedEvent")]

/**
 * DAO
 *
 * @author Ivan Latysh <ivanlatysh at gmail dot com>
 */
[Bindable]
public final class DAO extends EventDispatcher{

  /**
   * Static code for More... item
   */
  public static const SERVICE_CODE_MORE:String = "_more_";

  /**
   * Class instance
   */
  private static var instance:DAO = new DAO();

  public function DAO() {
    // forbid creating new instance of the class
    if( instance ) throw new Error( "DAO and can only be accessed through DAO.getInstance()" );
  }

  public static function getInstance():DAO {
    // return instance
    return instance;
  }

  /**
   * AddThis service endpoint
   * @see http://www.addthis.com/help/services-api
   */
  protected var serviceEndpoint:String = "http://cache.addthiscdn.com/services/v1/sharing.en.xml";

  /**
   * Small plus icon URL
   */
  protected var smPlusIconURL:String = "http://s7.addthis.com/static/btn/sm-plus.gif";

  /**
   * Services
   */
  protected var _services:ArrayCollection;

  /**
   * Add This icon
   */
  private var _addThisIcon:Bitmap;

  /**
   * Load services XML
   */
  public function initialize():void {
    // load services
    if (null==_services) loadServices();
  }

  /**
   * Return services XML 
   *
   * @return services XML
   */
  public function get services():ArrayCollection {
    return _services;
  }

  /**
   * Return AddThis icon
   *
   * @return icon
   */
  public function get addThisIcon():Bitmap {
    return _addThisIcon;
  }

  /**
   * Set AddThis icon
   * 
   * @param value icon
   */
  public function set addThisIcon(value:Bitmap):void {
    _addThisIcon = value;
  }

  /**
   * Load services
   */
  protected function loadServices():void {
    // create a new service
    var httpService:HTTPService = new HTTPService();
    httpService.method = "GET";
    httpService.resultFormat = "e4x";
    httpService.useProxy = false;
    httpService.url=serviceEndpoint;
    httpService.addEventListener(ResultEvent.RESULT, servicesReceived);
    httpService.addEventListener(FaultEvent.FAULT, HTTPFault);
    // call service
    var token:AsyncToken = httpService.send();
  }

  /**
   * Called when services data has been received
   *
   * @param event result event
   */
  protected function servicesReceived(event:ResultEvent):void {
    if (null == event.result) {
      Alert.show("Unable to load sharing destinations, result XML is null.");
    }
    // get service XMLList
    var _xmlList:XMLList = event.result.children().children().children();
    // create services array
    _services = new ArrayCollection();
    for each (var _s:* in _xmlList) {
      var _sObj:Service = new Service();
      _sObj.code = _s.code.text();
      _sObj.name = _s.name.text();
      _sObj.icon_url = _s.icon.text();
      _sObj.loadIcon();
      _services.addItem(_sObj);
    }
    // add `More...` element
    var _more:Service = new Service();
    _more.code = SERVICE_CODE_MORE;
    _more.name = "More...";
    _more.icon_url = smPlusIconURL;
    _more.loadIcon();
    _services.addItem(_more);

    // fire data loaded event
    dispatchEvent(new DataLoadedEvent());
  }

  /**
   * Default HTTP fault handler
   *
   * @param event fault event
   */
  public static function HTTPFault(event:FaultEvent):void {
    var message:String = "Ooops. We are sorry, but we could not load sharing destinations.";
    try {
      var responseMessage:String = event.message.body.toString();
      if (responseMessage.length>0) {
        message = responseMessage;
      }
    } catch (e:Error) {
      try {
        if (event.message.body.toString().length>0) {
          message = event.message.body.toString();
        }
      } catch (e1:Error) {
        if (event.fault.toString().length>0) {
          message = event.fault.toString();
        }
      }
    }
    // show an error message
    Alert.show(message, "Error");
  }

}

}